/**
 * 
 */
package com.wubo.sec.core;

import java.util.Collection;
import java.util.List;

import org.springframework.security.access.AccessDecisionVoter;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.vote.AbstractAccessDecisionManager;
import org.springframework.security.authentication.InsufficientAuthenticationException;
import org.springframework.security.core.Authentication;

/**
 * 同一类型任一通过即可，不同类型必须全部同意的AccessDecisionManager
 * @author WuBo
 * @CreateDate 2012-4-20
 */
@SuppressWarnings("unchecked")
public class CategoryAnyUnanimousBased extends AbstractAccessDecisionManager {
	
	public CategoryAnyUnanimousBased() {
    }

	public CategoryAnyUnanimousBased(List<AccessDecisionVoter> decisionVoters) {
        super(decisionVoters);
    }
	
	public void decide(Authentication authentication, Object object,
			Collection<ConfigAttribute> attributes)
			throws AccessDeniedException, InsufficientAuthenticationException {
		int grant = 0;
        int abstain = 0;

        for(AccessDecisionVoter voter : getDecisionVoters()) {
            int result = voter.vote(authentication, object, attributes);

            if (logger.isDebugEnabled()) {
                logger.debug("Voter: " + voter + ", returned: " + result);
            }

            switch (result) {
            case AccessDecisionVoter.ACCESS_GRANTED:
                grant++;

                break;

            case AccessDecisionVoter.ACCESS_DENIED:
                throw new AccessDeniedException(messages.getMessage("AbstractAccessDecisionManager.accessDenied",
                        "Access is denied"));

            default:
                abstain++;

                break;
            }
        }

        // To get this far, there were no deny votes
        if (grant > 0) {
            return;
        }

        // To get this far, every AccessDecisionVoter abstained
        checkAllowIfAllAbstainDecisions();
	}
}
